package org.http;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.concurrent.*;

/**
 * @author andy
 */
@Slf4j
public class HandleSocketData {

    //        序号	名称	类型	含义
//        1	corePoolSize	int	核心线程池大小
//        2	maximumPoolSize	int	最大线程池大小
//        3	keepAliveTime	long	线程最大空闲时间
//        4	unit	TimeUnit	时间单位
//        5	workQueue	BlockingQueue<Runnable>	线程等待队列
//        6	threadFactory	ThreadFactory	线程创建工厂
//        7	handler	RejectedExecutionHandler	拒绝策略
//        return new ThreadPoolExecutor(
//                2,
//                Integer.MAX_VALUE,
//                1L,
//                TimeUnit.SECONDS,
//                new ArrayBlockingQueue<Runnable>(3),
//                Executors.defaultThreadFactory(),
//                new ThreadPoolExecutor.AbortPolicy()
//        );

    public static ExecutorService newCachedThreadPool() {
        int corePoolSize = TinyWebServer.of().config.getCorePoolSize();
        int processors=  Runtime.getRuntime().availableProcessors();
        corePoolSize = corePoolSize == 0 ? processors * 2 : corePoolSize;
        return new ThreadPoolExecutor(corePoolSize, processors * 4, 1L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
    }

    private final ExecutorService executorService = newCachedThreadPool();
    private static HandleSocketData handleBody = null;

    public static HandleSocketData of(){
        return null != handleBody ? handleBody: new HandleSocketData();
    }


    /**
     * 处理信息
     * 将请求转给写 selectionKey.interestOps(SelectionKey.OP_WRITE);
     * @param selectionKey key
     * @param selector selector
     */
    public void handle(SelectionKey selectionKey, Selector selector, ServerSocketChannel serverSocketChannel) throws IOException {
        if(selectionKey.isValid()){
            if (selectionKey.isAcceptable()) {
                handleAccept(selector, serverSocketChannel);
            } else if (selectionKey.isReadable()) {
                executorService.execute(new RequestHandler(selectionKey));
            }
        }
    }

    /**
     * 将accept 转换成 read
     * @param selector selector
     */
    private void handleAccept(Selector selector, ServerSocketChannel serverSocketChannel) throws IOException {
        SocketChannel socketChannel = serverSocketChannel.accept();
        socketChannel.configureBlocking(false);
        socketChannel.register(selector, SelectionKey.OP_READ);
    }

}
